package com.xiaomaoguai.fcp.pre.kepler.router.handler.handlercontext;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.googlecode.aviator.AviatorEvaluator;
import com.xiaomaoguai.fcp.pre.kepler.router.async.RouterWorkPoolManager;
import com.xiaomaoguai.fcp.pre.kepler.router.async.WorkPool;
import com.xiaomaoguai.fcp.pre.kepler.router.buf.Buf;
import com.xiaomaoguai.fcp.pre.kepler.router.buf.BufClone;
import com.xiaomaoguai.fcp.pre.kepler.router.buf.CallbackWaitBuf;
import com.xiaomaoguai.fcp.pre.kepler.router.exception.HandlerNotFoundException;
import com.xiaomaoguai.fcp.pre.kepler.router.exception.RemoteException;
import com.xiaomaoguai.fcp.pre.kepler.router.exception.RouterException;
import com.xiaomaoguai.fcp.pre.kepler.router.async.delay.DelayTask;
import com.xiaomaoguai.fcp.pre.kepler.router.async.delay.RetryInfo;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.Branch;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.HandlerInfo;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.RouterInfo;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.api.Handler;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.api.HandlerContext;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.enums.CallBack;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.enums.HandleResult;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.enums.HandlerType;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.enums.Instruction;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.handlers.EmptyHeadHandler;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.handlers.EmptyTailHandler;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.handlers.RPCHandler;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.spi.HandlerManager;
import com.xiaomaoguai.fcp.pre.kepler.router.router.RouterPipeline;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

/**
 * Router流程上下文
 *
 * @param <I>
 * @author DH
 */
public abstract class AbstractHandlerContext<I> implements HandlerContext<I> {

	protected Logger log = LoggerFactory.getLogger(this.getClass());

	protected RouterInfo routerInfo;

	protected volatile HandlerContext<?> next;

	protected Handler<I> handler;

	protected HandleResult handleResult = HandleResult.SUCESS;

	protected I innerParam;

	/**
	 * 分支调用 true 直接中断 false 继续执行
	 *
	 * @param routerInfo
	 * @return boolean
	 */
	public boolean branchInvoke(RouterInfo routerInfo) {
		if (CollectionUtils.isNotEmpty(routerInfo.getBranchList())) {
			/*
			 * 为防止执行多次分支操作，当满足第一个分支条件后处理完成直接退出 谨慎编写分支判断条件
			 */
			for (Branch branch : routerInfo.getBranchList()) {
				if (branch.excRule(getBuf().getContext())) {
					Buf buf = getBuf();
					Map extensionResult = JSON.parseObject(branch.excExtensionEl(buf.getContext()), Map.class);
					if (extensionResult != null)
						buf.getContext().putAll(extensionResult);
					switch (branch.getBranchType()) {
						/* 在当前handler之后新增插入多个handler */
						case ADD:
							branch_add(branch);
							break;
						/* 直接跳转到指定handler */
						case GOTO:
							return branch_goto(branch);
						/* 新增pipe 填充空的headHandler 和当前pipe的tailHandler */
						case ADD_PIPELINE:
							return branch_add_pipeline(branch);
						/* 终止直接退出 */
						case TERMINATED:
							log.info("{} router {} terminated!", buf.getId(), name());
							if (buf.getRpcBuf())
								buf.setInstruction(Instruction.BREAK);
							return Boolean.TRUE;
						/* 退出时附加执行任务 */
						case EXITWITH:
							branch_exitwith(branch);
							if (buf.getRpcBuf())
								buf.setNextHandlerName("TAIL");
							return Boolean.TRUE;
						case GOTO_LAST:
							log.info("{} goto lastHandler {} ", buf.getId(), getRouter().getLast().name());
							getRouter().getLast().invokeHandler();
							if (buf.getRpcBuf())
								buf.setNextHandlerName("TAIL");
							return Boolean.TRUE;
						default:
							break;
					}
					break;
				}
			}
		}
		return Boolean.FALSE;
	}

	private void branch_add(Branch branch) {
		RouterPipeline<?, ?> router = getRouter();
		Buf buf = getBuf();
		// 获取下一个handler
		HandlerContext<?> nextHandlerContext = getNext();
		Integer currentIndex = router.getIndex(name(), order());
		String[] addHandlerNames = StringUtils.split(branch.getNextHandlerName(), ',');
		// 异步时准备创建一个新pipe在当前线程执行
		if (routerInfo.isAsync()) {
			List<RouterInfo> newRouterInfos = Lists.newArrayList();
			for (int i = 0; i < addHandlerNames.length; i++) {
				newRouterInfos.add(new RouterInfo(i + 1, addHandlerNames[i]).build());
			}
			RouterPipeline<Buf, Buf> pipeline = new RouterPipeline(new EmptyHeadHandler(), new EmptyTailHandler(),
					router.getRouterConfig(), router.getRouterName());
			log.info("{} added async handler {} after {}", buf.getId(), branch.getNextHandlerName(),
					routerInfo.getName());
			pipeline.setDefaultHeadHandler(router.getDefaultHeadHandler());
			pipeline.init(newRouterInfos).fireHandlers(BufClone.clone(getBuf()));
		} else {
			List<HandlerContext<?>> addHandlerContexts = Lists.newArrayList();
			HandlerContext<?> currentHandlerContext = this;
			for (int i = 0; i < addHandlerNames.length; i++) {
				HandlerContext<?> addHandlerContext = new DefaultHandlerContext(router)
						.setRouterInfo(new RouterInfo(order() + 1, addHandlerNames[i]).build());
				addHandlerContext.setHandler(HandlerManager.getHandler(addHandlerNames[i]));
				addHandlerContexts.add(addHandlerContext);
				currentHandlerContext = currentHandlerContext.setNext(addHandlerContext);
			}
			// 同步router中的initHadlerContexts
			router.addHandlerContexts(currentIndex + 1, addHandlerContexts);
			log.info("{} added sync handler {} after {}", buf.getId(), branch.getNextHandlerName(),
					routerInfo.getName());
			currentHandlerContext.setNext(nextHandlerContext);
		}
	}

	private boolean branch_goto(Branch branch) {
		Buf buf = getBuf();
		/* rpc调用时，分支需goto头尾节点，需执行空尾节点序列化返回值退出 */
		if (StringUtils.equalsAny(branch.getNextHandlerName(), "TAIL", "HEAD") && buf.getRpcBuf()) {
			buf.setNextHandlerName(branch.getNextHandlerName());
			getLast().invokeHandler();
			return Boolean.TRUE;
		}
		HandlerContext<?> gotoHandlerContext = getNextByNextHandlerName(branch.getNextHandlerName());
		/*
		 * 如果找不到指定handler时， rpc调用过来的buf填充handlername返回调用方继续执行 否则抛出异常
		 */
		if (gotoHandlerContext == null && buf.getRpcBuf()) {
			buf.setNextHandlerName(branch.getNextHandlerName());
		} else if (gotoHandlerContext == null) {
			throw new HandlerNotFoundException(branch.getNextHandlerName());
		} else {
			setNext(gotoHandlerContext);
			log.info("{} goto handler {} ", buf.getId(), branch.getNextHandlerName());
			gotoHandlerContext.invokeHandler();
		}
		return Boolean.TRUE;
	}

	private boolean branch_add_pipeline(Branch branch) {
		RouterPipeline<?, ?> router = getRouter();
		Buf buf = getBuf();
		RouterPipeline pipeline = router.newPipe(branch.getNextHandlerName(), branch.getDefineTailHandler());
		/*
		 * 分支为异步时routerWorkPool的workHandler中的onEvent会调用handlerContext的invokeHandler
		 * 而pipe的invokeHandler就是调用完整责任链 但需要先设置入参
		 * 注意：同步新增责任链后执行完新责任链直接跳转到tailHandlercontext
		 * 异步新增责任链后继续执行完原责任链接下来的handler
		 * buf在此时会变成非远程rpcBuf 防止远程调用时执行某些特殊处理
		 */
		if (branch.isAsync()) {
			WorkPool<HandlerContext<?>> workPool = RouterWorkPoolManager.getPool(branch.getAsyncWorkPool());
			Buf newBuf = BufClone.clone(buf);
			newBuf.setRpcBuf(Boolean.FALSE);
			newBuf.setCurrentRouterName(branch.getNextHandlerName());
			pipeline.setBuf(newBuf);
			pipeline.setInnerParam(newBuf.getContext());
			log.info("invoke async branch pipeline {} from {}, buf:{}", branch.getNextHandlerName(),
					router.getRouterName(), pipeline.getInnerParam());
			workPool.addTask(pipeline);
		} else {
			log.info("invoke sync branch pipeline {} from {}, buf:{}", branch.getNextHandlerName(),
					router.getRouterName(), buf);
			buf.setRpcBuf(Boolean.FALSE);
			pipeline.setBuf(buf);
			pipeline.fireHandlers(buf.getContext());
			router.setLast(pipeline.getLast());
			buf.setNextHandlerName("TAIL");
			return Boolean.TRUE;
		}
		if (buf.getRpcBuf())
			buf.setNextHandlerName("TAIL");
		return Boolean.FALSE;
	}

	private void branch_exitwith(Branch branch) {
		RouterPipeline<?, ?> router = getRouter();
		List<RouterInfo> exitWithRouterInfos = Lists.newArrayList();
		String[] exitWithHandlerNames = StringUtils.split(branch.getNextHandlerName(), ',');
		for (int i = 0; i < exitWithHandlerNames.length; i++) {
			RouterInfo addRouterInfo = new RouterInfo(i + 1, exitWithHandlerNames[i]).build();
			exitWithRouterInfos.add(addRouterInfo);
		}
		// 分支异步时创建的责任链为EmptyTailHandler，然后同步调用当前routerpipe的tailhandler
		if (branch.isAsync()) {
			RouterPipeline newPipe = new RouterPipeline(new EmptyHeadHandler(), new EmptyTailHandler(),
					router.getRouterConfig(), router.getRouterName());
			newPipe.setDefaultHeadHandler(router.getDefaultHeadHandler());
			newPipe.init(exitWithRouterInfos);
			WorkPool<HandlerContext<?>> workPool = RouterWorkPoolManager.getPool(branch.getAsyncWorkPool());
			newPipe.setInnerParam(BufClone.clone(getBuf()));
			log.info("invoke async branch pipeline {} from {}, buf:{}", newPipe.getRouterName(), router.getRouterName(),
					newPipe.getInnerParam());
			workPool.addTask(newPipe);
			getLast().invokeHandler();
		} else {// 同步调用时，创建的新责任链tailhandler为当前routerpipe的tailhandler
			RouterPipeline newPipe = new RouterPipeline(new EmptyHeadHandler(), getRouter().getTailHandler(),
					router.getRouterConfig(), router.getRouterName());
			newPipe.setDefaultHeadHandler(router.getDefaultHeadHandler());
			newPipe.init(exitWithRouterInfos);
			newPipe.fireHandlers(getBuf());
			getRouter().setLast(newPipe.getLast());
		}
	}

	private HandlerContext<?> getNextByNextHandlerName(String nextHandlerName) {
		if (StringUtils.isBlank(nextHandlerName))
			return null;
		int index = nextHandlerName.indexOf("-");
		if (index == -1) {
			return getHandlerContext(nextHandlerName, null);
		} else {
			return getHandlerContext(nextHandlerName.substring(0, index),
					Integer.valueOf(nextHandlerName.substring(index + 1)));
		}

	}

	@Override
	public I getInnerParam() {
		return innerParam;
	}

	@Override
	public void setInnerParam(I innerParam) {
		this.innerParam = innerParam;
	}

	@Override
	public HandlerContext<?> getNext() {
		return next;
	}

	@Override
	public HandlerContext<?> setNext(HandlerContext<?> nextHandlerContext) {
		this.next = nextHandlerContext;
		return next;
	}

	@Override
	public Instruction syncHandler() {
		Instruction instruction = fireRpcHandlerContexts();
		if (instruction == Instruction.BREAK || instruction == Instruction.EXIT) {
			return instruction;
		}
		return invokeCurrentHandler();
	}

	@Override
	public Buf invokeHandler() {
		Buf buf = getBuf();
		if (buf != null)
			buf.setCurrentHandlerName(name());

		try {
			// 判断是否为异步handler
			// 当异步是批转联时，直接退出
			// 为保证线程安全，创建一个独立handler的责任链
			if (routerInfo.isAsync()) {
				WorkPool<HandlerContext<?>> routerWorkPool = RouterWorkPoolManager
						.getPool(routerInfo.getAsyncWorkPool());
				Buf newBuf = BufClone.clone(buf);
				if (routerInfo.isCallBack()) {
					routerWorkPool.addTask(this);
					return new CallbackWaitBuf();
				} else {
					RouterPipeline<Buf, Buf> singleHandlerPipe = getRouter().newSingleHandlerPipe(this);
					singleHandlerPipe.setInnerParam(newBuf);
					singleHandlerPipe.invokeCurrentHandler();
					routerWorkPool.addTask(singleHandlerPipe);
				}
			} else {
				Instruction instruction = syncHandler();
				if (instruction == Instruction.EXIT) {
					return getLast().invokeHandler();
				} else if (instruction == Instruction.BREAK) {
					return getBuf();
				}
			}
			return next.invokeHandler();
		} catch (Throwable cause) {
			exceptionHandler(cause);
		}
		return getBuf();
	}

	/**
	 * handlerContext 异常处理 可以理解为高速公路的应急道 1、创建routerException
	 * 2、执行当前handler.exceptionCaught 3、执行当前handler策略 4、跳转到tailhandler处理
	 *
	 * @param cause
	 */
	@Override
	public void exceptionHandler(Throwable cause) {
		if (cause instanceof RemoteException || cause instanceof RouterException) {
			List<Throwable> list = ExceptionUtils.getThrowableList(cause);
			cause = list.size() < 2 ? cause : list.get(list.size() - 1);
		}
		RouterException routerException = new RouterException(this, cause);
		/* 当前handler异常处理 */
		handler.exceptionCaught(routerException);
		/* 执行当前handler策略 */
		ruleExecute();
		/* 直接跳转到tailhandler异常处理 */
		getRouter().getLast().fireExceptionCaught(routerException);
	}

	/**
	 * 1.（buf--->innerParam） 生成handler内部域 2.前置处理 可用于校验、埋点、mock等相关操作 3.业务处理 4.批转联
	 * 逐笔调用后续handler后退出 5.（innerParam--->buf）后置操作 填充buf、埋点、mock等相关操作 6.分支处理
	 */
	@Override
	public Instruction invokeCurrentHandler() {
		if (!StringUtils.equalsAny(name(), "HEAD", "TAIL"))
			log.info("bufId【{}】 {}/{}-{} begin", getBuf() == null ? "" : getBuf().getId(), getRouterInfo().getOrder(),
					getRouter().getRouterName(), name());
		/* 1.（buf--->innerParam） 生成handler内部域 */
		handler.genInnerParam(this);
		/* 2.前置处理 可用于校验、埋点、mock等相关操作 */
		handler.beforeHandle(this);
		/* 3.业务处理 */
		handler.handle(this);
		/* 4.判断handler是否是批转联 */
		if (handler.isB2O()) {
			return Instruction.EXIT;
		}
		/* 5.（innerParam--->buf）后置操作 填充buf、埋点、mock等相关操作 */
		handler.handleCompleted(this);
		boolean isRpc = handler instanceof RPCHandler;
		/* 6、本地执行策略，rpc时退出 */
		Instruction instruction = ruleExecute();
		if (instruction == Instruction.BREAK || instruction == Instruction.EXIT
				|| instruction == Instruction.CONTINUE) {
			log.info("bufId【{}】 routerName【{}】 handlerName【{}】instruction【{}】",
					getBuf().getId(), getRouter().getRouterName(), name(), instruction);
			return instruction;
		}
		/* 远程handler已经执行，rpc后不能执行 */
		if (!isRpc) {
			/* 7.分支处理 当GOTO GOTO_LAST 同步ADD_PIPE TERMINATED 时处理完退出 */
			if (branchInvoke(routerInfo))
				return Instruction.BREAK;
		}
		/*如果buf为callBack 中断责任链*/
		if(getBuf().getCallBack() == CallBack.WAIT){
			log.info("routerName【{}】callBack Wait", getRouter().getRouterName());
			return Instruction.BREAK;

		}
		return Instruction.EXCUTE;
	}

	@Override
	public Instruction fireRpcHandlerContexts() {
		final HandlerInfo handlerInfo = routerInfo.getHandlerInfo();
		String application = null;
		if (null != handlerInfo) {
			application = routerInfo.getHandlerInfo().getApplication();
		}

		// 头尾handler并且非共享的本地handler直接退出
		if (needskip(application)) {
			return Instruction.EXCUTE;
		}
		/*
		 * rpchandler时如果remoteInfos不为空代表之前一个handler必为rpchuandler
		 * 此时判断当前handler是否为shareHandler（所有应用共有）或者跟上一个handler的url是否为同一个
		 * 如果满足任意一个条件就添加到链式rpc中统一调用，不同则直接退出 须返回到最上层第一个rpchandler进行远程调用
		 * 执行完rpc后，清空buf的remoteInfos,防止后续rpchandler判断处理有误
		 * 将remoteinfos里面最后一个handlerContext的nexthandler置为当前handlerContext的nexthandler
		 */
		List<RouterInfo> remoteInfos = getBuf().getRemoteInfos();
		// 当routerInfo配置callback标识，直接将之后的routerinfo信息添加到remoteInfo
		log.debug("before routerInfo.isCallBack ====>routerName:{},routerInfo.isCallBack():{},routerInfoName:{}", getRouter().getRouterName(), routerInfo.isCallBack(), routerInfo.getName());
		if (routerInfo.isCallBack()) {
			log.debug("routerInfo.isCallBack ====> {},routerName:{}", "routerInfo.isCallBack", getRouter().getRouterName());
			getBuf().setCallBack(CallBack.YES);
			getBuf().addRemoteInfo(getNextRouterInfos(Lists.newArrayList()));
			return Instruction.EXCUTE;
		} else if (CollectionUtils.isNotEmpty(remoteInfos)) {
			// url为空则上一个handler为共享handler
			// getUrl为空则当前handler为共享handler
			if (allowSetNextAndFire(remoteInfos, remoteInfos.size(), application)) {
				remoteInfos.add(routerInfo);
				next.fireRpcHandlerContexts();
			}
			return Instruction.CONTINUE;
		} else if (StringUtils.isBlank(application)) {
			return Instruction.EXCUTE;
		} else {
			getBuf().addRemoteInfo(routerInfo);
			remoteInfos = getBuf().getRemoteInfos();
			next.fireRpcHandlerContexts();
		}
		invokeCurrentHandler();
		Buf buf = getBuf();
		log.info("bufId【{}】远程调用【{}】返回buf:{}", buf.getId(), application, buf.toJsonString());
		// callback wait时直接中断
		if (buf.getCallBack() == CallBack.WAIT) {
			return Instruction.BREAK;
		}
		if (buf.getInstruction() == Instruction.BREAK || buf.getInstruction() == Instruction.EXIT)
			return buf.getInstruction();
		/*
		 * 在rpc后，执行过goto goto_last add_pipe exitwith这些分支时
		 * buf会返回nexthandlername，直接从nexthandler开始执行剩余责任链
		 */
		String nextHandlerName = buf.getNextHandlerName();
		HandlerContext<?> nextHandlerContext = null;
		if (StringUtils.isBlank(nextHandlerName)) {
			RouterInfo lastRouterInfo = remoteInfos.get(remoteInfos.size() - 1);
			nextHandlerContext = getHandlerContext(lastRouterInfo.getName(), lastRouterInfo.getOrder()).getNext();
			Preconditions.checkNotNull(nextHandlerContext,
					"rpc completed notFound nextHandlerName" + lastRouterInfo.getName() + lastRouterInfo.getOrder());
		} else {
			nextHandlerContext = getNextByNextHandlerName(nextHandlerName);
			Preconditions.checkNotNull(nextHandlerContext, "rpc completed notFound nextHandlerName" + nextHandlerName);
		}
		// 重置rpc相关参数
		buf.setRemoteInfos(null);
		buf.setNextHandlerName(null);
		buf.setRpcBuf(Boolean.FALSE);
		nextHandlerContext.invokeHandler();
		return Instruction.BREAK;
	}

	/**
	 * 是否允许添加并执行rpc 注意batchhandler涉及到callback操作不能在远程调用链首个handler以外出现
	 *
	 * @param remoteInfos
	 * @param application
	 * @param cursor      从哪一个下标开始寻找
	 * @return boolean
	 */
	private boolean allowSetNextAndFire(List<RouterInfo> remoteInfos, Integer cursor, String application) {
		// 递归向上遍历 找到第一个rpchandler
		Integer index = cursor - 1;
		String url = remoteInfos.get(index).getUrl();
		if (StringUtils.isNotBlank(application) && StringUtils.isBlank(url)) {
			return allowSetNextAndFire(remoteInfos, index, application);
		} else {
			// 针对server端，共享handler可能会出现在这个位置，判断remoteLists包含则跳过
			return !remoteInfos.contains(routerInfo) && (StringUtils.isBlank(application)
					|| StringUtils.isAnyBlank(url, getUrl()) || url.equals(getUrl()));
		}
	}

	private Instruction ruleExecute() {
		if (StringUtils.isNoneBlank(routerInfo.getRule())) {
			Buf buf = getBuf();
			//rpc回到客户端执行
			if (buf.getRpcBuf()) {
				String nextHandlerName = StringUtils.equals(next.name(), "TAIL") ? null : next.name();
				buf.setNextHandlerName(nextHandlerName);
				log.info("【{}】 rpc 执行【{}】返回客户端执行 ruleExecute nextHandler【{}】", buf.getId(), name(), nextHandlerName);
				return Instruction.BREAK;
			}
			Map<String, String> params = (Map<String, String>) AviatorEvaluator.execute(routerInfo.getRule(),
					buf.getContext(), Boolean.TRUE);
			String instructionString = params.get("instruction");
			if (StringUtils.isBlank(instructionString)) {
				log.warn("{} {} 执行策略为空", buf.getId(), name());
				return Instruction.EXCUTE;
			}
			log.info("【{}】  ruleExecute instruction【{}】", buf.getId(), instructionString);
			Instruction instruction = Instruction.valueOf(instructionString);
			if (instruction == Instruction.RETRY) {
				DefaultHandlerContext<?> currentHandlerContext = (DefaultHandlerContext) this;
				RetryInfo retryInfo = currentHandlerContext.retry(params);
				if (retryInfo.getMaxRetryTimes() == -1 || retryInfo.getRetryTimes() <= retryInfo.getMaxRetryTimes()) {
					DelayTask.addTask((DefaultHandlerContext) this);
				} else {
					log.info("bufId【{}】 routerName【{}】 handlerName【{}】  msgId【{}】超过最大重试【{}】次，instruction 【EXIT】",
							buf.getId(), getRouter().getRouterName(), name(),
							retryInfo.getMsgId(), retryInfo.getMaxRetryTimes());
				}
				return Instruction.EXIT;
			}
			String routerName = params.get("routerName");
			if (instruction == Instruction.INVOKE_PIPE && StringUtils.isNoneBlank(routerName)) {
				RouterPipeline<?, ?> router = getRouter();
				log.info("rule invoke  pipeline {} from {}, buf:{}", routerName, router.getRouterName(), buf);
				router.newPipe(params.get("routerName")).setBuf(buf).fireHandlers(buf.getContext());
			}
			return instruction;
		}
		return Instruction.EXCUTE;

	}

	/**
	 * 头尾节点-->true 共享节点-->false
	 *
	 * @return boolean
	 */
	private boolean needskip(String application) {
		return StringUtils.equalsAny(name(), "HEAD", "TAIL")
				|| (routerInfo.matchHandlerType(HandlerType.LOCAL) && StringUtils.isNoneBlank(application));
	}

	@Override
	public String name() {
		return routerInfo.getName();
	}

	@Override
	public Integer order() {
		return routerInfo.getOrder();
	}

	@Override
	public String getNextHandlerName() {
		return next.name();
	}

	@Override
	public HandleResult getHandlerResult() {
		return handleResult;
	}

	@Override
	public void setHandlerResult(HandleResult handleResult) {
		this.handleResult = handleResult;
	}

	@Override
	public Handler<I> getHandler() {
		return handler;
	}

	@Override
	public HandlerContext<I> setHandler(Handler<I> handler) {
		this.handler = handler;
		return this;
	}

	@Override
	public HandlerContext<?> getHandlerContext(String handlerName, Integer order) {
		if (StringUtils.isBlank(handlerName))
			return null;
		if (handlerName.equals(name()) && (order == null || order == routerInfo.getOrder())) {
			return this;
		} else {
			return next.getHandlerContext(handlerName, order);
		}
	}

	@Override
	public RouterInfo getRouterInfo() {
		return routerInfo;
	}

	@Override
	public HandlerContext<I> setRouterInfo(RouterInfo routerInfo) {
		this.routerInfo = routerInfo;
		return this;
	}

	@Override
	public HandlerContext<?> getLast() {
		return next.getLast();
	}

	@Override
	public void fireExceptionCaught(RouterException e) {
		if (e.getHandlerContext() == this) {
			handler.exceptionCaught(e);
		}
		next.fireExceptionCaught(e);
	}

	/**
	 * getBuf需要子类自行实现
	 *
	 * @return buf
	 */
	@Override
	public abstract Buf getBuf();

	@Override
	public Buf putBuf(String key, Object value) {
		return getBuf().put(key, value);
	}

	@Override
	public Buf setNewBuf(Buf buf) {
		getRouter().setBuf(buf);
		return buf;
	}

	@Override
	public boolean isRpc() {
		return routerInfo.matchHandlerType(HandlerType.RPC);
	}

	@Override
	public String getUrl() {
		return routerInfo.getUrl();
	}

	@Override
	public String toString() {
		return new ToStringBuilder(this).append("routerInfo", routerInfo)
				.append("next", next == null ? "" : next.name()).append("handler", handler)
				.append("handleResult", handleResult).append("innerParam", innerParam).toString();
	}

	@Override
	public List<RouterInfo> getNextRouterInfos(List<RouterInfo> routerInfos) {
		routerInfos.add(routerInfo);
		if (next != null && !(next instanceof TailContext)) {
			log.debug("getNextRouterInfos: next:{}", next.getClass().getName());
			next.getNextRouterInfos(routerInfos);
		}
		return routerInfos;
	}

}
